﻿using LayuiMvc.DataEntity;
using LayuiMvc.DataEntity.DataEnum;
using LayuiMvc.DataEntity.IdentityEntity;
using LayuiMvc.DataEntity.IdentityStore;
using LayuiMvc.DataModel.Identity;
using LayuiMvcUtil.Exception;
using LayuiMvcUtil.Result;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;

namespace LayuiMvc.Logic.Identity
{
    public class IdentityUserManager:UserManager<IdentityUserEntity,int>
    {
        /// <summary>
        /// 用户管理器
        /// 注意：
        /// 1.管理器不直接与数据库进行通信，而是通过存储器进行通信的
        /// 2.存储器中包括了一些常用CRUD方法
        /// </summary>
        /// <param name="store"></param>
        public IdentityUserManager(IdentityUserStore store) : base(store)
        {
        }
        #region 用户管理==用户注册

       
        public async Task UserRegisterAsync(UserRegisterModel registerModel)
        {
            IdentityUserEntity userEntity = new IdentityUserEntity()
            {
                UserName = Guid.NewGuid().ToString("N"),
                NickName = registerModel.NickName,
                PhoneNumber = registerModel.PhoneNumber,
                RegisterTime = DateTime.Now,
                UserIdentity=UserIdentityEnum.CommonStudent,
                Email = registerModel.Email
            };

            IdentityResult result = await base.CreateAsync(userEntity, registerModel.Password);

            if (!result.Succeeded)
            {
                throw new CustomException("用户注册失败");
            }
        }

        #endregion

        #region 用户管理==修改密码
        public async Task UpdateUserPasswordAsync(UpdatePasswordModel updatePasswordModel)
        {
            IdentityResult result = await base.ChangePasswordAsync(updatePasswordModel.UserId, updatePasswordModel.OldPassword, updatePasswordModel.NewPassword);
            if (!result.Succeeded)
            {
                throw new CustomException("用户密码修改失败");
            }
        }
        #endregion

        #region 用户管理==修改个人信息
        /// <summary>
        /// 用户个人信息修改初始化
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public async Task<UserMsgModel> UpdateUserMsgInit(int userId)
        {
            //根据用户Id查找用户实体
            IdentityUserEntity userEntity = await base.FindByIdAsync(userId);

            UserMsgModel userMsgModel = new UserMsgModel()
            {
                UserId = userEntity.Id,
                NickName = userEntity.NickName,
                Sex = userEntity.Sex,
                HeadImgUrl = userEntity.HeadImgUrl,
                PhoneNumber = userEntity.PhoneNumber,
                Email = userEntity.Email,
                RegisterTime = userEntity.RegisterTime.ToString("yyyy-MM-dd HH:mm:ss"),
                UserIdentity=userEntity.UserIdentity
                
            };

            return userMsgModel;
        }

        /// <summary>
        /// 修改用户头像
        /// </summary>
        /// <param name="userId">用户id</param>
        /// <param name="headImgUrl">头像地址</param>
        /// <returns></returns>
        public async Task UpdateUserHeadImgAsync(int userId,string headImgUrl)
        {
            IdentityUserEntity userEntity = await base.FindByIdAsync(userId);

            userEntity.HeadImgUrl = headImgUrl;

            IdentityResult result = await base.UpdateAsync(userEntity);
            if (!result.Succeeded)
            {
                throw new CustomException("用户头像信息修改失败");
            }
        }
        /// <summary>
        /// 修改用户信息
        /// </summary>
        /// <param name="userMsgModel">修改完成后的用户模型类</param>
        /// <returns></returns>
        public async Task UpdateUserMsgAsync(UserMsgModel userMsgModel)
        {
            IdentityUserEntity userEntity = await base.FindByIdAsync(userMsgModel.UserId);

            userEntity.Sex = userMsgModel.Sex;
            userEntity.NickName = userEntity.NickName;

            IdentityResult result = await base.UpdateAsync(userEntity);

            if (!result.Succeeded)
            {
                throw new CustomException("用户头像信息修改失败");
            }
        }
        #endregion

        #region 用户管理==用户列表

        /// <summary>
        /// 用户列表
        /// </summary>
        /// <param name="pageIndex">当前页索引</param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        public async Task<DataResult<List<UserMsgModel>>> UserListAsync(int pageIndex,int pageSize)
        {
            DataResult<List<UserMsgModel>> rtnResult = new DataResult<List<UserMsgModel>>();

            IQueryable<IdentityUserEntity> query = base.Users.OrderByDescending(m => m.RegisterTime);

            rtnResult.count = await query.CountAsync();

            List<UserMsgModel> userList = await query.Skip((pageIndex - 1) * pageSize).Take(pageSize).Select(m => new UserMsgModel()
            {
                UserId = m.Id,
                NickName = m.NickName,
                PhoneNumber = m.PhoneNumber,
                Email = m.Email,
                Sex = m.Sex,
                IsBanned = m.IsBanned
            }).ToListAsync();

            rtnResult.data = userList;
            return rtnResult;
        }

        #endregion

        #region  用户管理==修改状态

        public async Task ChangeUserStatusAsync(int userId)
        {
            IdentityUserEntity userEntity = await base.FindByIdAsync(userId);

            userEntity.IsBanned = !userEntity.IsBanned;

            IdentityResult result = await base.UpdateAsync(userEntity);

            if (!result.Succeeded)
            {
                throw new CustomException("用户状态修改失败");
            }
        }

        #endregion

        #region 用户管理==选择角色

        /// <summary>
        /// 用户角色列表初始化
        /// </summary>
        /// <param name="page">当前页索引</param>
        /// <param name="limit">每页的记录条数</param>
        /// <param name="roleManager">角色管理器</param>
        /// <param name="userId">用户id</param>
        /// <returns></returns>
        public async Task<DataResult<List<RoleModel>>> UserRoleAsync(int page,int limit,
            IdentityRoleManager roleManager,int userId)
        {
            DataResult<List<RoleModel>> rtnResult = new DataResult<List<RoleModel>>();

            IQueryable<IdentityRoleEntity> query = roleManager.Roles.OrderBy(m => m.Id);

            rtnResult.count = await query.CountAsync();

            //当前用户所拥有的角色列表
            IList<string> userRoleList = await base.GetRolesAsync(userId);

            List<RoleModel> roleList = await query.Skip((page - 1) * limit).Take(limit).Select(m =>
                new RoleModel()
                {
                    RoleId = m.Id,
                    RoleName = m.Name,
                    Description = m.Description,
                    LAY_CHECKED = userRoleList.Any(n => n.Contains(m.Name))
                }).ToListAsync();

            rtnResult.data = roleList;
            return rtnResult;
        }

        /// <summary>
        /// 选择角色
        /// </summary>
        /// <param name="userId">用户id</param>
        /// <param name="roleName"></param>
        /// <returns></returns>
        public async Task SelectUserRoleAsync(int userId,string[] roleName)
        {
            //获取当前用户的角色列表
            IList<string> userRolelist = await base.GetRolesAsync(userId);

            await base.RemoveFromRolesAsync(userId, userRolelist.ToArray());
            await base.AddToRolesAsync(userId, roleName);
        }

        #endregion

        #region 用户管理==添加声明
        public async Task UserClaimAddAsync(List<Claim> claimList,int userId)
        {
            //删除用户之前的声明
            IList<Claim> userClaimList = await base.GetClaimsAsync(userId);
            foreach (Claim claim in userClaimList)
            {
                await base.RemoveClaimAsync(userId, claim);
            }

            foreach (Claim claim in claimList)
            {
                await base.AddClaimAsync(userId, claim);
            }
        }
        #endregion

        public static IdentityUserManager Create(IdentityFactoryOptions<IdentityUserManager> options,IOwinContext context)
        {
            //从Owin宿主中获取数据库上下文
            EFContext db = context.Get<EFContext>();
            //获取用户管理器
            IdentityUserManager userManager = new IdentityUserManager(new IdentityUserStore(db));

            return userManager;
        }
    }
}
